package fr.insee.solr.service.state;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.beanutils.NestedNullException;
import org.apache.commons.beanutils.PropertyUtils;

import fr.insee.solr.model.FieldStrategy;
import fr.insee.solr.model.annotation.SolrField;
import fr.insee.solr.service.impl.SolrInseeException;

public class StateSimpleMultivaluedStrategy implements IState {

	@Override
	public Object getValue(Field f, SolrField a, Object o) throws SolrInseeException {
		List<Object> liste = new ArrayList<>();

		try {
			Object iterable = PropertyUtils.getProperty(o, f.getName());

			if (iterable != null && iterable instanceof Iterable<?>) {
				FieldStrategy strategy = a.fieldStrategy().newInstance();
				for (Object v : (Iterable<?>) iterable) {
					Object value = strategy.getValue(null, v);
					if (value != null) {
						liste.add(value);
					}
				}
			}

		}
		catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | InstantiationException e) {
			new SolrInseeException(ERROR_NO_SUCH_FIELD + a.fieldName(), e);
		}
		catch (NestedNullException e) {
			return null;
		}

		if (liste.isEmpty()) {
			liste = null;
		}

		return liste;
	}

	@Override
	public void fillValue(Object bean, Field f, SolrField a, Object solrValue) throws SolrInseeException {
		try {
			Class<?> typeListe = PropertyUtils.getPropertyType(bean, f.getName());
			Collection<Object> collection = StateUtils.createCollection(typeListe);

			if (solrValue != null && solrValue instanceof Collection) {
				ParameterizedType listeType = (ParameterizedType) f.getGenericType();
				Class<?> classGeneric = (Class<?>) listeType.getActualTypeArguments()[0];
				FieldStrategy strategy = a.fieldStrategy().newInstance();
				for (Object o : ((Collection<?>) solrValue)) {
					Object value = strategy.fillValue(null, classGeneric.newInstance(), o.toString());

					if (value != null) {
						collection.add(value);
					}
				}
			}

			if (collection != null) {
				PropertyUtils.setProperty(bean, f.getName(), collection);
			}
		}
		catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | InstantiationException e) {
			throw new SolrInseeException(ERROR_FILL_FIELD + f.getName(), e);
		}
	}

}
